package com.liujit.standard.basis.admin.config.aop;

import cn.hutool.core.util.StrUtil;
import com.liujit.standard.basis.admin.model.SysMenu;
import com.liujit.standard.basis.admin.service.SysUserService;
import com.liujit.standard.basis.admin.util.ApiUtil;
import com.liujit.standard.basis.admin.config.annotation.Auth;
import com.liujit.standard.basis.core.constants.RedisConstants;
import com.liujit.standard.basis.core.domain.result.UserInfo;
import com.liujit.standard.basis.core.enums.ResultCode;
import com.liujit.standard.basis.core.exception.BusinessException;
import com.liujit.standard.basis.core.service.RedisService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @description: 自定义权限校验
 * @author: liujun
 * @create: 2021/3/24 5:43 下午
 **/
@Configuration
@Aspect
public class AuthAop {

    @Resource
    private RedisService redisService;

    @Resource
    private SysUserService sysUserService;

    @Around("within(@org.springframework.web.bind.annotation.RestController *) && @annotation(com.liujit.standard.basis.admin.config.annotation.Auth)")
    public Object authMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取方法
        Object target = joinPoint.getTarget();
        String methodName = joinPoint.getSignature().getName();
        // 获取参数类型
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
        Method method = target.getClass().getMethod(methodName, parameterTypes);
        Auth auth = method.getAnnotation(Auth.class);
        if (auth != null) {
            /*获取用户权限*/
            UserInfo user = ApiUtil.getSysUser();
            if (user == null) {
                throw new BusinessException(ResultCode.USER_NOT_LOGGED_IN);
            }
            String authKey = RedisConstants.AUTH_PREFIX + user.getId();
            Object o = redisService.get(authKey);
            if (o == null) {
                // 根据ID查询用户权限
                List<SysMenu> authList = sysUserService.getAuths(user.getId(), user.getLoginName());
                List<String> auths = new ArrayList<>();
                for (SysMenu sm : authList) {
                    if (StrUtil.isNotEmpty(sm.getAuthCode())) {
                        auths.add(sm.getAuthCode());
                    }
                }
                redisService.set(authKey, auths, 30L, TimeUnit.MINUTES);
                o = auths;
            }
            List<String> authList = (List<String>) o;
            String value = auth.value();
            if (StrUtil.isNotEmpty(value)) {
                if (authList.indexOf(value) < 0) {
                    throw new BusinessException(ResultCode.PERMISSION_NO_ACCESS);
                }
            }
        }

        Object proceed = joinPoint.proceed();
        return proceed;
    }
}
